﻿#pragma once
#include <fstream>//ReadFileToBinary
#include <iomanip> 
#include "zyEnvironment.h"
#include "zyWindow.h"
#include <atlbase.h>

//#pragma comment(lib,"comctl32.lib")
//#pragma comment(lib, "Gdiplus.lib")

#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")



BlackMoonUI::zyObject* BlackMoonUI::黑月取资源控件(HWND 参数_父窗口句柄, const std::wstring& 参数_控件名) {
    return 子程序_取资源控件(参数_父窗口句柄, 参数_控件名);
}
BlackMoonUI::zyObject* BlackMoonUI::子程序_取资源控件(HWND 参数_父窗口句柄, const std::wstring& 参数_控件名) {
    HWND firstChild = GetWindow(参数_父窗口句柄, GW_CHILD);
    HWND next = firstChild;
    while (next) {
        zyObject* pWindow = zyEnv::getInstance().getWndObject(next);
        if (pWindow) {
            if (lstrcmp(参数_控件名.c_str(), pWindow->getStringData(L"name").c_str()) == 0) {
                return pWindow;
            }
            zyObject* Window = 子程序_取资源控件(next, 参数_控件名);
            if (Window) {
                return Window;
            }
        }
        next = GetWindow(next, GW_HWNDNEXT);
    }
    return nullptr;
}

HWND BlackMoonUI::黑月取根窗口(HWND 参数_窗口句柄)
{
    HWND hWnd = 参数_窗口句柄;
    HWND hWndParent = 参数_窗口句柄;
    while (hWndParent) {
        zyObject* obj = zyEnv::getInstance().getWndObject(hWndParent);
        if (!obj) return 0;
        std::wstring type = obj->getStringData(L"Type");
        if (lstrcmp(type.c_str(), L"窗口") == 0 || lstrcmp(type.c_str(), L"对话框") == 0)
        {
            return hWndParent;
        }
        hWnd = hWndParent;
        hWndParent = GetParent(hWndParent);
    }
    return hWnd;
}
RECT BlackMoonUI::黑月到屏幕矩形(HWND 参数_窗口句柄, RECT& 参数_矩形) {
    // 转换左上角
    POINT pt = { 参数_矩形.left, 参数_矩形.top };
    ClientToScreen(参数_窗口句柄, &pt);
    参数_矩形.left = pt.x;
    参数_矩形.top = pt.y;

    // 转换右下角（保持为点坐标）
    pt.x = 参数_矩形.right;
    pt.y = 参数_矩形.bottom;
    ClientToScreen(参数_窗口句柄, &pt);
    参数_矩形.right = pt.x;
    参数_矩形.bottom = pt.y;


    RECT rc = 参数_矩形;
    /*POINT pt = { 0 };
    GetWindowRect(参数_窗口句柄, &参数_矩形);
    HWND hParent = GetParent(参数_窗口句柄);
    pt.x = 参数_矩形.left;
    pt.y = 参数_矩形.top;
    ClientToScreen(hParent, &pt);
    参数_矩形.left = pt.x;
    参数_矩形.top = pt.y;
    pt.x = 参数_矩形.right;
    pt.y = 参数_矩形.bottom;
    ClientToScreen(hParent, &pt);
    参数_矩形.right = pt.x;
    参数_矩形.bottom = pt.y;*/
    return rc;
}
RECT BlackMoonUI::黑月到窗口矩形(HWND 参数_窗口句柄, RECT& 参数_屏幕矩形) {
    // 转换左上角
    POINT pt = { 参数_屏幕矩形.left, 参数_屏幕矩形.top };
    ScreenToClient(参数_窗口句柄, &pt);
    参数_屏幕矩形.left = pt.x;
    参数_屏幕矩形.top = pt.y;

    // 转换右下角（保持为点坐标）
    pt.x = 参数_屏幕矩形.right;
    pt.y = 参数_屏幕矩形.bottom;
    ScreenToClient(参数_窗口句柄, &pt);
    参数_屏幕矩形.right = pt.x;
    参数_屏幕矩形.bottom = pt.y;

    RECT rc = 参数_屏幕矩形;
    /*POINT pt = { 0 };
    GetWindowRect(参数_窗口句柄, &参数_屏幕矩形);
    HWND hParent = GetParent(参数_窗口句柄);
    pt.x = 参数_屏幕矩形.left;
    pt.y = 参数_屏幕矩形.top;
    ScreenToClient(hParent, &pt);
    参数_屏幕矩形.left = pt.x;
    参数_屏幕矩形.top = pt.y;
    pt.x = 参数_屏幕矩形.right;
    pt.y = 参数_屏幕矩形.bottom;
    ScreenToClient(hParent, &pt);
    参数_屏幕矩形.right = pt.x;
    参数_屏幕矩形.bottom = pt.y;*/
    return rc;

}
int BlackMoonUI::黑月默认ID() {
    static int id;
    id = id + 1;
    return id;
}
RECT BlackMoonUI::zyStringToRECT(const wchar_t* wstr) {
    int x, y, w, h;
    swscanf_s(wstr, L"%d,%d,%d,%d", &x, &y, &w, &h);
    return RECT{ x, y, w, h };
}
// 自定义 PathRemoveFileSpec 函数 路径中移除文件名部分
bool BlackMoonUI::zyPathRemoveFileSpec(wchar_t* path)
{
    if (path == nullptr || *path == L'\0')
    {
        return false; // 路径为空，无法处理
    }
    // 查找最后一个路径分隔符（支持 '/' 和 '\'）
    size_t lastSeparator = std::wcsrchr(path, L'\\') - path;
    if (lastSeparator == static_cast<size_t>(-1))
    {
        lastSeparator = std::wcsrchr(path, L'/') - path;
    }
    if (lastSeparator == static_cast<size_t>(-1))
    {
        // 没有找到路径分隔符，说明路径中没有目录部分
        path[0] = L'\0';
        return false;
    }
    // 移除文件名部分，保留目录部分
    path[lastSeparator] = L'\0';
    return true;
}
void BlackMoonUI::zySetCurrentDirectoryToProcessDirectory()
{
    wchar_t path[MAX_PATH];
    GetModuleFileName(nullptr, path, MAX_PATH);
    zyPathRemoveFileSpec(path);
    SetCurrentDirectory(path);
}
// 将二进制数据保存到.h文件中
void BlackMoonUI::zySaveBinaryToHeaderFile(const std::vector<unsigned char>& data, const char* outputFilename, const char* arrayName) {
    std::ofstream out(outputFilename);
    if (!out) {
        std::wcout << L"无法创建输出文件: " << outputFilename << std::endl;
        return;
    }

    out << "#pragma once\n\n";
    out << "// 自动生成的二进制数据\n";
    out << "const unsigned char " << arrayName << "[] = {\n";
    for (size_t i = 0; i < data.size(); ++i) {
        out << "0x" << std::hex << std::setw(2) << std::setfill('0')
            << static_cast<int>(data[i]);

        if (i != data.size() - 1) {
            out << ", ";
        }

        if ((i + 1) % 16 == 0) {
            out << "\n";
        }
    }

    out << "\n};\n\n";
    out << "const size_t " << arrayName << "= " << std::dec << data.size() << ";\n";

    std::wcout << L"已生成头文件: " << outputFilename << std::endl;
}
std::vector<BYTE> BlackMoonUI::zyReadFileToBinary(const std::wstring& filePath)
{
    std::ifstream file(filePath, std::ios::binary | std::ios::ate);
    if (!file.is_open())
    {
        std::wcerr << L"无法打开文件: " << filePath << std::endl;
        return {};
    }

    std::streamsize size = file.tellg();
    file.seekg(0, std::ios::beg);

    std::vector<unsigned char> buffer(size);
    if (file.read(reinterpret_cast<char*>(buffer.data()), size))
    {
        std::wcout << L"文件读取成功，大小: " << size << L" 字节" << std::endl;
    }
    else
    {
        std::wcerr << L"文件读取失败: " << filePath << std::endl;
        return {};
    }

    return buffer;
}
BOOL BlackMoonUI::zyReadFile(LPCWSTR filePath, std::vector<CHAR>* retData)
{
    BOOL fOK = FALSE;
    if (filePath != L"") {
        HANDLE hFile = CreateFileW(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile != INVALID_HANDLE_VALUE) {
            DWORD nSize = GetFileSize(hFile, NULL);
            if (nSize != INVALID_FILE_SIZE) {
                (*retData).resize(nSize);
                fOK = ReadFile(hFile, &(*retData)[0], nSize, &nSize, NULL);
            }
            CloseHandle(hFile);
        }
    }
    return fOK;
}
BOOL BlackMoonUI::preTranslateMessage(HWND hWnd, zyObject* this_, MSG& msg)
{
    // 使用更合适的类型来避免强制类型转换  
    if (this_ == nullptr)
        return FALSE;
    if (msg.message == WM_KEYDOWN) {
        switch (msg.wParam) {
            case VK_TAB: // 使用VK_TAB代替硬编码的9  
            {
                LRESULT zyStyle = (LRESULT)this_->getPtrData(L"zyStyle");
                if ((zyStyle & ZY窗口风格_需要TAB键) == 0) {
                    bool bShiftPressed = (GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0; // 使用VK_SHIFT和32768=十六进制掩码  
                    HWND hWnd_ = GetNextDlgTabItem(hWnd, reinterpret_cast<HWND>(this_->getPtrData(L"hWnd")), bShiftPressed);
                    if (hWnd_ != NULL) {
                        SetFocus(hWnd_);
                        return FALSE; // 使用FALSE而不是false（在WinAPI中更常见）  
                    }
                }
            }
            break;
            case VK_ESCAPE: // 使用VK_ESCAPE代替硬编码的27  
            {
                SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), 0);  //MAKEWPARAM=合并整数
                return FALSE;
            }
            case VK_RETURN: // 使用VK_RETURN代替硬编码的13  
            {
                LRESULT zyStyle = (LRESULT)this_->getPtrData(L"zyStyle");
                if ((zyStyle & ZY窗口风格_需要回车键) == 0) {
                    LRESULT ret = SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDOK, 0), 0);
                    return ret == 0;
                }
            }
            break;
        }
    }
    return TRUE;
}

LRESULT WINAPI BlackMoonUI::WndProc_(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message == WM_NCCREATE)
    {
        CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lParam);
        if (cs && cs->lpCreateParams) {
            zyObject* base = reinterpret_cast<zyObject*>(cs->lpCreateParams);
            if (base != nullptr) {
                base->setPtrData(L"hWnd", (void*)hWnd);
                zyEnv::getInstance().registerWnd(hWnd, base);
            }
        }
    }
    zyObject* Ptr = zyEnv::getInstance().getWndObject(hWnd);
    if (Ptr != nullptr) {
        BOOL bHand = false;
        LRESULT ret = Ptr->callWndProc(hWnd, message, wParam, lParam, &bHand);
        if (bHand) {
            return ret;
        }
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}

ATOM BlackMoonUI::MyRegisterClass(HINSTANCE hInstance, const std::wstring& 参数_类名, WNDPROC 参数_窗口过程, HICON 参数_图标句柄, int 参数_类风格)
{

    WNDCLASSEX wcex = {0};
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = (参数_类风格 == -1) ? (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS) : 参数_类风格;
    wcex.lpfnWndProc = 参数_窗口过程 ? 参数_窗口过程 : WndProc_;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = (参数_图标句柄 == 0) ? LoadIcon(nullptr, IDI_APPLICATION) : 参数_图标句柄;
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_BTNSHADOW);
    wcex.lpszMenuName = nullptr;
    wcex.lpszClassName = 参数_类名.c_str();
    wcex.hIconSm = 参数_图标句柄;
    return RegisterClassEx(&wcex);
}


BlackMoonUI::zyApplications::zyApplications()
{
    m_hInst = GetModuleHandle(NULL);
    m_bEnableDpiConvert = FALSE;

    //初始化GDI+
    Gdiplus::GdiplusStartupInput StartupInput;
    StartupInput.GdiplusVersion = 1;
    StartupInput.DebugEventCallback = NULL;
    StartupInput.SuppressBackgroundThread = FALSE;
    StartupInput.SuppressExternalCodecs = FALSE;
    Gdiplus::GdiplusStartup(&m_pGdiToken, &StartupInput, NULL);
}
BlackMoonUI::zyApplications::~zyApplications()
{
    Gdiplus::GdiplusShutdown(m_pGdiToken);
}
void BlackMoonUI::zyApplications::初始化(HINSTANCE hInstance, BOOL 参数_使用ATL, UINT 参数_通用控件类)
{
    if (hInstance != NULL)
        setHandle(hInstance);
    if (参数_通用控件类 == 0)
        参数_通用控件类 = 65535;
    if (参数_使用ATL)
        AtlAxWinInit_();
    INITCOMMONCONTROLSEX icc = { 0 };
    icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icc.dwICC = 参数_通用控件类;
    InitCommonControlsEx(&icc);
    SetProcessDPIAware();
    enableDpiConvert(TRUE);
}
int BlackMoonUI::zyApplications::运行(zyWindow& bform, BOOL Bshow) {
    if (!bform.isWindow())
        return 1;

    if (Bshow)
        bform.show();

    MSG msg = { 0 };
    while (GetMessage(&msg, nullptr, 0, 0) > 0) {
        // 获取顶级窗口
        HWND hWndTop = GetAncestor(msg.hwnd, GA_ROOT);
        zyObject* base = zyEnv::getInstance().getWndObject(hWndTop);

        // 处理 MDI 系统加速键
        HWND hWndMDIClient = base ? (HWND)base->getPtrData(L"hWndMDIClient") : nullptr;
        if (hWndMDIClient && TranslateMDISysAccel(hWndMDIClient, &msg)) {
            continue;
        }

        // 处理加速表
       
        HACCEL pAccelTable = base ? (HACCEL)base->getPtrData(L"pAccelTable") : nullptr;
        if (pAccelTable && TranslateAccelerator(hWndTop, pAccelTable, &msg)) {
            continue;
        }

        // 处理键盘和鼠标消息
        LRESULT retAtl = 0;
        if ((msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) ||
            (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST)) {
            HWND hWndCtl = msg.hwnd;
            do {
                zyObject* tempThis = zyEnv::getInstance().getWndObject(hWndCtl);
                if (tempThis && tempThis->getPtrData(L"zyOCX")) {
                    retAtl = SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)&msg);
                    break;
                }
                hWndCtl = GetParent(hWndCtl);
            } while (hWndCtl);
        }

        // 处理预翻译消息
        if (retAtl == 0 && (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST)) {
            if (base && !preTranslateMessage(hWndTop, base, msg)) {
                continue;
            }
        }

        // 处理其他消息
        if (retAtl == 0) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        // 检查窗口是否已销毁
        if (!bform.isWindow())
            break;
    }

    // 处理 GetMessage 错误
    if (GetMessage(&msg, nullptr, 0, 0) == -1) {
        // 处理错误，例如记录日志或采取其他措施
        // 这里可以根据具体需求添加错误处理逻辑
    }

    return 0;
}
/*
int BlackMoonUI::zyApplications::运行(zyWindow& bform, BOOL Bshow) {
    if (bform.isWindow() == false)
        return 1;
    if (Bshow)
        bform.show();

    MSG msg = { 0 };
    while (GetMessage(&msg, 0, 0, 0))
    {
        void* LinkAtls = nullptr;
        HACCEL pAccelTable = nullptr;
        HWND hWndMDIClient = nullptr;
        LRESULT retAtl = 0;
        HWND hWndTop = GetAncestor(msg.hwnd, GA_ROOT);
        zyObject* base = zyEnv::getInstance().getWndObject(hWndTop);
        if (base != nullptr) {
            hWndMDIClient = (HWND)base->getPtrData(L"hWndMDIClient");
            LinkAtls = base->getPtrData(L"ATLWindows");
            pAccelTable = (HACCEL)base->getPtrData(L"pAccelTable");
        }
        if (hWndMDIClient != 0) {
            if (TranslateMDISysAccel(hWndMDIClient, &msg) != 0) {
                continue;
            }
        }
        // 处理加速表
        
        if (pAccelTable && TranslateAccelerator(hWndTop, pAccelTable, &msg)) {
            
            continue;
        }
        base = zyEnv::getInstance().getWndObject(msg.hwnd);
        // 处理键盘和鼠标消息
        if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST ||
            msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) {
            HWND hWndCtl = msg.hwnd;
            do {
                zyObject* tempThis = zyEnv::getInstance().getWndObject(hWndCtl);
                if (tempThis && tempThis->getPtrData(L"zyOCX")) {
                    retAtl = SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)&msg);
                    break;
                }
                hWndCtl = GetParent(hWndCtl);
            } while (hWndCtl != nullptr);
        }
        // 处理预翻译消息
        if (retAtl == 0 && msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) {
            if (base && !preTranslateMessage(hWndTop, base, msg)) {
                continue;
            }
        }

        if (retAtl != 0) {
            continue;
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        // 检查窗口是否已销毁
        if (!bform.isWindow())
            break;
    }
    return 0;
}*/

int BlackMoonUI::zyApplications::AtlAxWinInit_() {
    // 使用局部静态变量来自动处理线程安全和只初始化一次的问题  
    static HMODULE hModule = LoadLibrary(L"atl.dll");
    static int (WINAPI * AtlAxWinInit)() = reinterpret_cast<int (WINAPI*)()>(GetProcAddress(hModule, "AtlAxWinInit"));

    // 检查是否成功获取了函数指针  
    if (AtlAxWinInit == nullptr) {
        // 如果未能获取函数指针，则可能是找不到 DLL 或函数名错误  
        // 这里可以添加错误处理代码，比如记录日志或返回错误码  
        return -1; // 假设返回 -1 表示失败  
    }
    // 调用函数  
    return AtlAxWinInit();
}
std::wstring BlackMoonUI::zyApplications::GetDirectory() const {
    wchar_t buffer[MAX_PATH];
    GetModuleFileName(getHandle(), buffer, MAX_PATH);
    PathRemoveFileSpec(buffer);
    return std::wstring(buffer);
}
int BlackMoonUI::zyApplications::取命令行(std::vector<std::wstring>& 参数_命令行参数) {//返回数组成员数
    int count = 0;
    LPWSTR* args = CommandLineToArgvW(GetCommandLine(), &count);
    if (args == nullptr)
        return 0;
    参数_命令行参数.resize(count);
    for (int i = 0; i < count; i++) {
        参数_命令行参数[i] = args[i];
    }
    return (int)参数_命令行参数.size();
}
std::wstring BlackMoonUI::zyApplications::GetFileName() const {
    wchar_t buffer[MAX_PATH];
    GetModuleFileName(getHandle(), buffer, MAX_PATH);
    return PathFindFileName(buffer);
}
std::wstring BlackMoonUI::zyApplications::GetRoute() const
{
    //CXTextA szPath[MAX_PATH];
    wchar_t buffer[MAX_PATH]; // 用于存储注册表值的缓冲区
    //DWORD bufferSize = sizeof(buffer); // 缓冲区的大小
    GetModuleFileName(getHandle(), buffer, MAX_PATH);
    return std::wstring(buffer);
}
void BlackMoonUI::zyApplications::结束()
{
    PostQuitMessage(0);
}
//获取DPI
int BlackMoonUI::zyApplications::getDpiForWindow() {
    HDC hdc = GetDC(NULL);
    int dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
    int dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
    ReleaseDC(NULL, hdc);
    return (((dpiX) > (dpiY)) ? (dpiX) : (dpiY));
};
void BlackMoonUI::zyApplications::dpiConvert(POINT& pt) {
    if (!m_bEnableDpiConvert)
        return;

    //auto getDpiForWindow = []() -> int {
    //    HDC hdc = GetDC(NULL);
    //    int dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
    //    int dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
    //    //ReleaseDC(NULL, hdc);
    //    return (((dpiX) > (dpiY)) ? (dpiX) : (dpiY));
    //};

    static int dpi = getDpiForWindow();
    pt.x = (LONG)((pt.x * dpi) / 96.0);
    pt.y = (LONG)((pt.y * dpi) / 96.0);
}
//启用DPI转换
void BlackMoonUI::zyApplications::enableDpiConvert(BOOL bEnable) {
    m_bEnableDpiConvert = bEnable;
}
//注册窗口
void BlackMoonUI::zyApplications::registerWnd(HWND hWnd, zyObject* pObject) {
    m_wndEventMap[hWnd] = pObject;
}
//移除窗口
void BlackMoonUI::zyApplications::unregisterWnd(HWND hWnd) {
    m_wndEventMap.erase(hWnd);
}
//获取窗口对象
BlackMoonUI::zyObject* BlackMoonUI::zyApplications::getWndObject(HWND hWnd) {
    auto it = m_wndEventMap.find(hWnd);
    if (it != m_wndEventMap.end())
        return it->second;
    return nullptr;
}
//获取模块句柄
HINSTANCE BlackMoonUI::zyApplications::getHandle() const {
    return m_hInst;
}
//设置模块句柄
void BlackMoonUI::zyApplications::setHandle(HINSTANCE hInst) {
    m_hInst = hInst;
}